"""
file: myGraph.py
language: python3
authors: Zack Butler, Sean Strout
authors: Graph routines.  The graph is undirected and implemented as an 
    adjacency list.
"""

class Node:
    """
     Node represents a node in a graph using adjacency lists.
         Node.name is a String.
         Node.neighbors is a ListOfNode.
    """
    __slots__ = ( 'name', 'neighbors' )
    
    def __init__(self, name):
        """
        __init__: Node * String -> None
        Constructs a node object with the given name and no neighbors.
        """
        self.name = name
        self.neighbors = []
        
    def __str__(self):
        """
        __str__ : Node -> String
        Returns a string with the name of the node and its neighbors' names.
        """
        result = str(self.name) + ': '
        if len(self.neighbors) > 0:
            for i in range(len(self.neighbors) - 1): # last is different
                result += str(self.neighbors[i].name) + ', '
            result += str(self.neighbors[-1].name)   # -1 index accesses last 
        return result


def loadGraph(filename):
    """
     loadGraph : String -> dict(String:Node)
     Loads graph data from the file with the given name.  loadGraph assumes 
     that each line contains two words representing two nodes connected by 
     an edge.  loadGraph forms edges in both directions between the nodes.
     loadGraph creates Node instances as needed and returns a list of nodes 
     representing the graph.
     Pre-conditions: file content is well-formed, containing two names per
     line.
    """
    graph = {}
    for line in open(filename):
        contents = line.split()
        if contents[0] not in graph:
            n1 = Node(contents[0])
            graph[contents[0]] = n1
        else:
            n1 = graph[contents[0]]
        if contents[1] not in graph:
            n2 = Node(contents[1])
            graph[contents[1]] = n2
        else:
            n2 = graph[contents[1]]
        if n2 not in n1.neighbors:
            n1.neighbors.append( n2 )
        if n1 not in n2.neighbors:
            n2.neighbors.append( n1 )
    return graph
